<?php
declare (strict_types = 1);
/**
 * @copyright Copyright (c) 2025 
 * @license https://opensource.org/licenses/Apache-2.0
 * @link https://blog.gougucms.com
 */



namespace app\admin\controller;

use app\admin\BaseController;
use app\admin\model\AdminLog;
use app\admin\validate\AdminCheck;
use think\exception\ValidateException;
use think\facade\Db;
use think\facade\Session;
use think\Image;
use PhpOffice\PhpSpreadsheet\IOFactory;

use app\admin\model\Goods as GoodsModel;

use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use PhpOffice\PhpSpreadsheet\Style\Alignment;
use PhpOffice\PhpSpreadsheet\Style\Fill;
use PhpOffice\PhpSpreadsheet\Style\Border;
use PhpOffice\PhpSpreadsheet\Style\Font;
use PhpOffice\PhpSpreadsheet\Style\Color;
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
use PhpOffice\PhpSpreadsheet\Settings;
use PhpOffice\PhpSpreadsheet\Collection\CellsFactory;

class Api extends BaseController
{
    //上传文件
    public function upload()
    {
        $param = get_params();
		$sourse = 'file';
		if(isset($param['sourse'])){
			$sourse = $param['sourse'];
		}
		if($sourse == 'file' || $sourse == 'tinymce'){
			if(request()->file('file')){
				$file = request()->file('file');
			}
			else{
				return to_assign(1, '没有选择上传文件');
			}
		}
		else{
			if (request()->file('editormd-image-file')) {
				$file = request()->file('editormd-image-file');
			} else {
				return to_assign(1, '没有选择上传文件');
			}
		}
        // 获取上传文件的hash散列值
        $sha1 = $file->hash('sha1');
        $md5 = $file->hash('md5');
        $rule = [
            'image' => 'jpg,png,jpeg,gif',
            'doc' => 'doc,docx,ppt,pptx,xls,xlsx,pdf',
            'file' => 'zip,gz,7z,rar,tar',
            'video' => 'mpg,mp4,mpeg,avi,wmv,mov,flv,m4v',
			'audio' => 'mp3,wav,wma,flac,midi',
        ];
		
		$fileExt = $rule['image'] . ',' . $rule['doc'] . ',' . $rule['file'] . ',' . $rule['video'] . ',' . $rule['audio'];
		//1M=1024*1024=1048576字节
		$file_size = get_system_config('other','upload_max_filesize');
		if(!isset($file_size)){
			$file_size=50;
		}
		$fileSize = $file_size * 1024 * 1024;
		if (isset($param['type']) && $param['type']) {
			$fileExt = $rule[$param['type']];
		}
		if (isset($param['size']) && $param['size']) {
			$fileSize = $param['size'];
		}
		$validate = \think\facade\Validate::rule([
			'image' => 'require|fileSize:' . $fileSize . '|fileExt:' . $fileExt,
		]);
        $file_check['image'] = $file;
        if (!$validate->check($file_check)) {
            return to_assign(1, $validate->getError());
        }
        // 日期前綴
        $dataPath = date('Ym');
        $use = 'thumb';
        $filename = \think\facade\Filesystem::disk('public')->putFile($dataPath, $file, function () use ($md5) {
            return $md5;
        });
        if ($filename) {

            $path = get_config('filesystem.disks.public.url');
			$filepath = $path . '/' . $filename;
			if(isset($param['thumb'])){
				$realPath = CMS_ROOT . "public" . $path . '/' . $filename;
				$image = Image::open($realPath);
				// 按照原图的比例生成一个最大为500*500的缩略图并保存为thumb.png
				$image->thumb(500, 500,Image::THUMB_CENTER)->save($realPath.'_thumb.'.$file->extension());
				$filepath = $filepath .'_thumb.'.$file->extension();
			}
			
            //写入到附件表
            $data = [];
            $data['filepath'] = $filepath;
            $data['name'] = $file->getOriginalName();
            $data['mimetype'] = $file->getOriginalMime();
            $data['fileext'] = $file->extension();
            $data['filesize'] = $file->getSize();
            $data['filename'] = $filename;
            $data['sha1'] = $sha1;
            $data['md5'] = $md5;
            $data['module'] = \think\facade\App::initialize()->http->getName();
            $data['action'] = app('request')->action();
            $data['uploadip'] = app('request')->ip();
            $data['create_time'] = time();
            $data['user_id'] = get_login_admin('id') ? get_login_admin('id') : 0;
            if ($data['module'] = 'admin') {
                //通过后台上传的文件直接审核通过
                $data['status'] = 1;
                $data['admin_id'] = $data['user_id'];
                $data['audit_time'] = time();
            }
            $data['use'] = request()->has('use') ? request()->param('use') : $use; //附件用处
            $res['id'] = Db::name('file')->insertGetId($data);
            $res['filepath'] = $data['filepath'];
            $res['name'] = $data['name'];
            $res['filename'] = $data['filename'];
            add_log('upload', $data['user_id'], $data,'文件');
			if($sourse == 'editormd'){
				//editormd编辑器上传返回
				return json(['success'=>1,'message'=>'上传成功','url'=>$data['filepath']]);
			}
			else if($sourse == 'tinymce'){
				//tinymce编辑器上传返回
				return json(['success'=>1,'message'=>'上传成功','location'=>$data['filepath']]);
			}
			else{
				//普通上传返回
				return to_assign(0, '上传成功', $res);
			}            
        } else {
            return to_assign(1, '上传失败，请重试');
        }
    }

	//上传excel文件
    public function uploadExcel()
    {
        
		header('Content-Type: text/csv; charset=UTF-8');
		$param = get_params();
		$sourse = 'file';
		if(isset($param['sourse'])){
			$sourse = $param['sourse'];
		}
		if($sourse == 'file' || $sourse == 'tinymce'){
			if(request()->file('file')){
				$file = request()->file('file');
			}
			else{
				return to_assign(1, '没有选择上传文件');
			}
		}
		else{
			if (request()->file('editormd-image-file')) {
				$file = request()->file('editormd-image-file');
			} else {
				return to_assign(1, '没有选择上传文件');
			}
		}
        // 获取上传文件的hash散列值
        $sha1 = $file->hash('sha1');
        $md5 = $file->hash('md5');
        $rule = [
            'image' => 'jpg,png,jpeg,gif',
            'doc' => 'doc,docx,ppt,pptx,xls,xlsx,pdf',
            'file' => 'zip,gz,7z,rar,csv',
            'video' => 'mpg,mp4,mpeg,avi,wmv,mov,flv,m4v',
			'audio' => 'mp3,wav,wma,flac,midi',
        ];
		
		$fileExt = $rule['image'] . ',' . $rule['doc'] . ',' . $rule['file'] . ',' . $rule['video'] . ',' . $rule['audio'];
		//1M=1024*1024=1048576字节
		$file_size = get_system_config('other','upload_max_filesize');
		if(!isset($file_size)){
			$file_size=50;
		}
		$fileSize = $file_size * 1024 * 1024;
		
		if (isset($param['type']) && $param['type']) {
			$fileExt = $rule[$param['type']];
		}
		if (isset($param['size']) && $param['size']) {
			$fileSize = $param['size'];
		}
		$validate = \think\facade\Validate::rule([
			'image' => 'require|fileSize:' . $fileSize . '|fileExt:' . $fileExt,
		]);
        $file_check['image'] = $file;
        if (!$validate->check($file_check)) {
            return to_assign(1, $validate->getError());
        }
		
        // 日期前綴
        $dataPath = date('Ym');
		
        $use = 'thumb';
        $filename = \think\facade\Filesystem::disk('public')->putFile($dataPath, $file, function () use ($md5) {
            return $md5;
        });
        if ($filename) {

            $path = get_config('filesystem.disks.public.url');
			$filepath = $path . '/' . $filename;

			try {

				$reader = IOFactory::createReader('Csv');
				// 设置文件原始编码（根据实际情况调整）

                // 可选：处理带BOM头的UTF-8文件
                // 正确设置 BOM 处理（新版本）
                if (method_exists($reader, 'setPreserveBOM')) {
                    $reader->setPreserveBOM(true); // 保留 BOM 头
                }elseif (method_exists($reader, 'setReadBOM')) {
                    $reader->setReadBOM(true); // 兼容旧版本
                }
                $encoding = $this->detectFileEncoding($_FILES['file']['tmp_name']);
                $reader->setInputEncoding($encoding);
                //$reader->setInputEncoding('SJIS'); // 对于日文文件
				$spreadsheet = $reader->load($_FILES['file']['tmp_name']);
				$worksheet = $spreadsheet->getActiveSheet();
				$rows = $worksheet->toArray();
				// 删除标题行（第一行）
				array_shift($rows);

				// 准备SQL语句（防SQL注入）
				//$stmt = $conn->prepare("INSERT INTO products (name, price, stock) VALUES (?, ?, ?)");
				//$stmt->bind_param("sdi", $name, $price, $stock);
                $key_array  = range(25, 25 + 3*19, 3);
				$imported_rows = $empty_int = 0;
                $repeat_array = [];
				foreach ($rows as $row) {
					// 跳过空行
					if(empty($row[0])){
                        $empty_int ++;
					    continue;
                    }
					// 赋值
                    $pics = array();
                    foreach ($key_array as $v){
                        $pics[] = $row[$v];
                    }
                    // 判断重复
                    $id = Db::name('goods')->where(['spu_id'=>$row[0]])->value('id');
                    if(!empty($id)){
                        $repeat_array[] = $row[0];
                        continue;
                    }

                    $tips = !empty($row[96]) ? explode('|',$row[96]) : [];
					$excel_data[] = array(
						'spu_id'=> $row[0],
						'type'  => !empty($row[1]) ? 1 : 2,
						'title'  => !empty($row[2]) ? $row[2] : '',
						'tips'   => $row[96],
						'sku_id'  => $row[207],
						'thumb'  => '',
						'sku_key'=>!empty($tips[0]) ? $tips[0] : '',
                        'sku_key2'=>!empty($tips[1]) ? $tips[1] : '',
                        'sku_key3'=>!empty($tips[2]) ? $tips[2] : '',
						'sku_value'=>$row[97],
                        'sku_value2'=>$row[98],
                        'sku_value3'=>$row[99],
                        'is_mail'=>1,
						'base_price'=> $row[220],
                        'stocks'=> 5,
						'content'  => json_encode([$row[97],$row[98],$row[99]]),
						'pics'     => json_encode($pics),
						'admin_id' => get_login_admin('id') ? get_login_admin('id') : 0,
						'create_time' => time(),
                        'intro'    =>  json_encode($row)
					);
					$imported_rows++;
				
				}
				if(!empty($excel_data)){
                     \think\facade\Db::name('goods')->strict(false)->field(true)->insertAll($excel_data);
                    //写入到附件表
                    $data = [];
                    $data['filepath'] = $filepath;
                    $data['name'] = $file->getOriginalName();
                    $data['mimetype'] = $file->getOriginalMime();
                    $data['fileext'] = $file->extension();
                    $data['filesize'] = $file->getSize();
                    $data['filename'] = $filename;
                    $data['sha1'] = $sha1;
                    $data['md5'] = $md5;
                    $data['module'] = \think\facade\App::initialize()->http->getName();
                    $data['action'] = app('request')->action();
                    $data['uploadip'] = app('request')->ip();
                    $data['create_time'] = time();
                    $data['user_id'] = get_login_admin('id') ? get_login_admin('id') : 0;
                    if ($data['module'] = 'admin') {
                        //通过后台上传的文件直接审核通过
                        $data['status'] = 1;
                        $data['admin_id'] = $data['user_id'];
                        $data['audit_time'] = time();
                    }
                    $data['use'] = request()->has('use') ? request()->param('use') : $use; //附件用处
                    $res['id'] = Db::name('file')->insertGetId($data);
                    $res['filepath'] = $data['filepath'];
                    $res['name'] = $data['name'];
                    $res['filename'] = $data['filename'];
                    add_log('upload', $data['user_id'], $data,'文件');
                }
			} catch (Exception $e) {
					return to_assign(1, '上传失败，请重试');
			}

            $msg = "本次导入：成功 ".$imported_rows." 条 ；";
            if($empty_int > 0 ){
                $msg .= "空行".$empty_int." 条；";
            }
            if(count($repeat_array) > 0 ){
                $msg .= "重复".count($repeat_array)." 条，重复的SPU为：".implode("，", $repeat_array);
            }
			return to_assign(0, $msg, '');
        } else {
            return to_assign(1, '上传失败，请重试');
        }
    }

    //导入PC端说明文
    public function uploadExcel_pc()
    {

        header('Content-Type: text/csv; charset=UTF-8');
        $param = get_params();
        $sourse = 'file';
        if(isset($param['sourse'])){
            $sourse = $param['sourse'];
        }
        if($sourse == 'file' || $sourse == 'tinymce'){
            if(request()->file('file')){
                $file = request()->file('file');
            }
            else{
                return to_assign(1, '没有选择上传文件');
            }
        }
        else{
            if (request()->file('editormd-image-file')) {
                $file = request()->file('editormd-image-file');
            } else {
                return to_assign(1, '没有选择上传文件');
            }
        }
        // 获取上传文件的hash散列值
        $sha1 = $file->hash('sha1');
        $md5 = $file->hash('md5');
        $rule = [
            'image' => 'jpg,png,jpeg,gif',
            'doc' => 'doc,docx,ppt,pptx,xls,xlsx,pdf',
            'file' => 'zip,gz,7z,rar,csv',
            'video' => 'mpg,mp4,mpeg,avi,wmv,mov,flv,m4v',
            'audio' => 'mp3,wav,wma,flac,midi',
        ];

        $fileExt = $rule['image'] . ',' . $rule['doc'] . ',' . $rule['file'] . ',' . $rule['video'] . ',' . $rule['audio'];
        //1M=1024*1024=1048576字节
        $file_size = get_system_config('other','upload_max_filesize');
        if(!isset($file_size)){
            $file_size=50;
        }
        $fileSize = $file_size * 1024 * 1024;

        if (isset($param['type']) && $param['type']) {
            $fileExt = $rule[$param['type']];
        }
        if (isset($param['size']) && $param['size']) {
            $fileSize = $param['size'];
        }
        $validate = \think\facade\Validate::rule([
            'image' => 'require|fileSize:' . $fileSize . '|fileExt:' . $fileExt,
        ]);
        $file_check['image'] = $file;
        if (!$validate->check($file_check)) {
            return to_assign(1, $validate->getError());
        }

        // 日期前綴
        $dataPath = date('Ym');

        $use = 'thumb';
        $filename = \think\facade\Filesystem::disk('public')->putFile($dataPath, $file, function () use ($md5) {
            return $md5;
        });
        if ($filename) {

            $path = get_config('filesystem.disks.public.url');
            $filepath = $path . '/' . $filename;

            try {

                $reader = IOFactory::createReader('Csv');
                // 设置文件原始编码（根据实际情况调整）

                // 可选：处理带BOM头的UTF-8文件
                // 正确设置 BOM 处理（新版本）
                if (method_exists($reader, 'setPreserveBOM')) {
                    $reader->setPreserveBOM(true); // 保留 BOM 头
                }elseif (method_exists($reader, 'setReadBOM')) {
                    $reader->setReadBOM(true); // 兼容旧版本
                }
                $encoding = $this->detectFileEncoding($_FILES['file']['tmp_name']);
                $reader->setInputEncoding($encoding);
                //$reader->setInputEncoding('SJIS'); // 对于日文文件
                $spreadsheet = $reader->load($_FILES['file']['tmp_name']);
                $worksheet = $spreadsheet->getActiveSheet();
                $rows = $worksheet->toArray();
                // 删除标题行（第一行）
                //array_shift($rows);

                // 准备SQL语句（防SQL注入）
                //$stmt = $conn->prepare("INSERT INTO products (name, price, stock) VALUES (?, ?, ?)");
                //$stmt->bind_param("sdi", $name, $price, $stock);
                $key_array  = range(25, 25 + 3*19, 3);
                $imported_rows = $empty_int = 0;
                $repeat_array = [];
                foreach ($rows as $row) {
                    // 跳过空行
                    if(empty($row[0])){
                        continue;
                    }
                    Db::name('goods')->where(['spu_id'=>$row[1],'type'=>1])->save(['pc_url'=>$row[0]]);
                }

            } catch (Exception $e) {
                return to_assign(1, '上传失败，请重试');
            }
            $msg = "本次导入成功 ";
            return to_assign(0, $msg, '');
        } else {
            return to_assign(1, '上传失败，请重试');
        }
    }
    private function detectFileEncoding($filename) {
        $content = file_get_contents($filename);

        // 检测常见中文编码
        $encodings = [
            'UTF-8', 'GBK', 'GB2312', 'BIG5',
            'UTF-16LE', 'UTF-16BE', 'ISO-8859-1','SJIS'
        ];

        $detected = mb_detect_encoding($content, $encodings, true);

        // 如果没有检测到，尝试更精确的检测
        if (!$detected) {
            if (preg_match('/[\x80-\xFF]/', $content)) {
                if (preg_match('/^\xEF\xBB\xBF/', $content)) {
                    return 'UTF-8'; // 带BOM的UTF-8
                }
                return 'GBK'; // 默认中文编码
            }
            return 'ASCII'; // 纯ASCII
        }

        return $detected;
    }
	/****导出表格二****/
	public function export(){

        // 设置内存和时间限制以适应大数据量
        ini_set('memory_limit', '2048M');
        set_time_limit(600);
		// 创建新的电子表格

		$spreadsheet = new Spreadsheet();
		$sheet = $spreadsheet->getActiveSheet();

		// 设置文档属性
		$spreadsheet->getProperties()
			->setCreator("产品数据导出系统")
			->setTitle("产品信息报表")
			->setDescription("包含所有产品详细信息的完整报表");
        		// =============== 设置第一行样式 ===============
		// 第一行合并单元格设置
		$merges = [
			['A1:I1', 'SPU(相同信息可以填写一样的)'],   // 9列
			['J1:Z1', 'SKU'],                         // 17列 (J-Z:17列)
			['AA1:AF1', '普通报关信息'],               // 6列 (AA-AF:6列)
			['AG1:AN1', '报关特殊属性'],               // 8列 (AG-AN:8列)
			['AO1:AO1', '图片信息'],                  // 1列
			['AP1:AQ1', '质检制作要求']                // 2列
		];

		foreach ($merges as $merge) {
			list($range, $text) = $merge;
			$sheet->mergeCells($range);
			$sheet->setCellValue(explode(':', $range)[0], $text);
		}

		// 第一行整体样式
		$firstRowStyle = [
			'font' => [
				'bold' => true,
				'size' => 12,
				'color' => ['rgb' => Color::COLOR_WHITE],
				'name' => '微软雅黑'
			],
			'alignment' => [
				'horizontal' => Alignment::HORIZONTAL_CENTER,
				'vertical' => Alignment::VERTICAL_CENTER
			],
			'fill' => [
				'fillType' => Fill::FILL_SOLID,
				'startColor' => ['rgb' => '3498db']
			],
			'borders' => [
				'allBorders' => [
					'borderStyle' => Border::BORDER_THIN,
					'color' => ['rgb' => '000000']
				]
			]
		];
		$sheet->getStyle('A1:AQ1')->applyFromArray($firstRowStyle);
		$sheet->getRowDimension(1)->setRowHeight(25);

		// =============== 设置第二行样式 ===============
		// 第二行表头
		$headers = [
			'SPU', '产品标题', 'ERP类目', '来源URL', '来源备注', '默认供应商名称', 
			'富文本描述', '纯文本描述', '短描述', 'SKU', '图片URL',
			'规格1名称', '规格1值', '规格2名称', '规格2值', 
			'规格3名称', '规格3值', '规格4名称', '规格4值', '规格5名称', '规格5值', 
			'成本价(￥)', '重量(g)', '长(cm)', '宽(cm)', '高(cm)', 
			'中文名称', '英文名称', '材质', '申报价值(USD)', '报关重量(g)', '海关编码', 
			'带电(非内置)', '带电(内置)', '带电(纯电池)', '带磁', '液体', '粉末', '刀具', '危险品', 
			'产品图片(URL)', '项目名', '标准描述'
		];

		// 应用表头
		for ($i = 0; $i < count($headers); $i++) {
			$colLetter = Coordinate::stringFromColumnIndex($i + 1);
			$cell = $colLetter . '2';
			$sheet->setCellValue($cell, $headers[$i]);
		}

		// 第二行样式
		$secondRowStyle = [
			'font' => [
				'bold' => true,
				'size' => 10,
				'name' => '微软雅黑'
			],
			'alignment' => [
				'horizontal' => Alignment::HORIZONTAL_CENTER,
				'vertical' => Alignment::VERTICAL_CENTER,
				'wrapText' => true
			],
			'fill' => [
				'fillType' => Fill::FILL_SOLID,
				'startColor' => ['rgb' => 'e3f2fd']
			],
			'borders' => [
				'allBorders' => [
					'borderStyle' => Border::BORDER_THIN,
					'color' => ['rgb' => '000000']
				]
			]
		];
		$sheet->getStyle('A2:AQ2')->applyFromArray($secondRowStyle);
		$sheet->getRowDimension(2)->setRowHeight(30);
        $sheet->getStyle('K')->getAlignment()->setWrapText(true);
		// 自动调整列宽
		for ($col = 1; $col <= 43; $col++) {
			$sheet->getColumnDimensionByColumn($col)->setAutoSize(true);
		}

		// =============== 从第三行开始填充数据 ===============
            $param = get_params();
            $where[] = ['a.delete_time', '=', 0];
            $where[] = ['a.type', '=', 1];
            if (!empty($param['ids'])) {
                $where[] = ['a.id', 'in',$param['ids']];
            }
            $admin_id = get_login_admin('id') ? get_login_admin('id') : 0;
            if($admin_id != 1){
                $where[] = ['admin_id','=',$admin_id];
            }
			$param = get_params();
            $GoodsModel = new GoodsModel();
			//$list = $GoodsModel->getGoodsList($where, $param);

			$GoodsModel = $GoodsModel::where($where);
			if( !empty($param['start_date']) && !empty($param['end_date']) ) {
				$GoodsModel->whereBetweenTime('create_time',$param['start_date'],date('Y-m-d',strtotime($param['end_date'])+86400));
			}elseif(!empty($param['start_date']) && empty($param['end_date'])){
				$GoodsModel->whereTime('create_time', '>=', strtotime($param['start_date']) );
			}elseif( empty($param['start_date'])  && !empty($param['end_date']) ){
				$GoodsModel->whereTime('create_time', '<=', strtotime($param['end_date'])+86400 );;
			}else{
                $GoodsModel->whereBetweenTime('create_time',date('Y-m-d'),date('Y-m-d',strtotime(date('Y-m-d'))+86400));
            }
			$list  = $GoodsModel
					->field('a.*')
					->alias('a')
					->order('a.id desc')
					->select();
			$sampleData = array();
			$list = json_decode(json_encode($list),true);
			//$url = "https://image.rakuten.co.jp/like-shop/cabinet";
			if(!empty($list)){
				foreach($list as $value){
                    /*
				    $base_price = [];
                    $goods = db('goods')
                        ->where('spu_id',$value['spu_id'])
                        ->where('type',2)
                        ->field('base_price,intro')
                        ->select();
                    foreach ($goods as $k=>$v){
                        $intro = isset($v['intro']) ? json_decode($v['intro'],true) : '';
                        $base_price[$intro[209]] = $v['base_price'];
                    }*/
				    $content = json_decode($value['content'],true);
				    $pics    = !empty($value['pics']) ? $this->buildImagePathString(json_decode($value['pics'],true),$value['address']) : '';
                    //$csvContent = '"' . str_replace('"', '""', $pics) . '"';
					//$color = !empty($value['sku_value']) ? $this->splitString($value['sku_value']) : [];
                    //$size  = !empty($value['sku_value2']) ? $this->splitString($value['sku_value2']) : [];
                    //$other = !empty($value['sku_value3']) ? $this->splitString($value['sku_value3']) : [];
                    $color = !empty($content[0]) ? $this->splitString($content[0]) : [];
                    $size  = !empty($content[1]) ? $this->splitString($content[1]) : [];
                    $other = !empty($content[2]) ? $this->splitString($content[2]) : [];
                    $array = $this->arrayCombineWithKeys($color,$size,$other);
                    if(!empty($array)){
                        foreach ($array as $k=>$v){
                            $sampleData[] = [
                                $value['spu_id'], $value['title'], '', $value['banner'], '',  $value['desc'],
                                '', '', '', $value['spu_id'].'_'.$k, '',
                                $value['sku_key'], $v[0], $value['sku_key2'], $v[1]??'', $value['sku_key3'], $v[2]??'', '', '', '', '',
                                $value['base_price'], '', '', '', '', '', '', '', '', '', '',
                                '', '', '', '', '', '', '', '', $pics, '', ''
                            ];
                        }
                    }else{
                        $sampleData[] = [
                            $value['spu_id'], $value['title'], '', '', '', '',
                            '', '', '', $value['spu_id'], '',
                            '', '', '', '', '','', '', '', '', '', '',
                            '', '', '', '', '', '', '', '', '', '', '',
                            '', '', '', '', '', '', '', '', '', '', ''
                        ];
                    }

				}
			}
		// 填充数据到第三行开始

		$row = 3;
		foreach ($sampleData as $data) {
			for ($col = 0; $col < count($headers); $col++) {
				$colLetter = Coordinate::stringFromColumnIndex($col + 1);
				$cell = $colLetter . $row;
				$value = $data[$col] ?? ''; // 防止索引超出范围
				$sheet->setCellValue($cell, $value);
			}
			$row++;
		}

		// 数据行样式
		$dataStyle = [
			'alignment' => [
				'vertical' => Alignment::VERTICAL_CENTER,
				'wrapText' => true
			],
			'borders' => [
				'allBorders' => [
					'borderStyle' => Border::BORDER_THIN,
					'color' => ['rgb' => 'D3D3D3']
				]
			]
		];
		$sheet->getStyle('A3:AQ' . ($row - 1))->applyFromArray($dataStyle);

		// 设置交替行颜色
		for ($i = 3; $i < $row; $i++) {
			$fillColor = ($i % 2 == 1) ? 'FFFFFF' : 'f9f9f9';
			$sheet->getStyle('A' . $i . ':AQ' . $i)->getFill()
				->setFillType(Fill::FILL_SOLID)
				->getStartColor()->setRGB($fillColor);
		}

		// 设置数值列格式
		$sheet->getStyle('V3:V' . ($row - 1))->getNumberFormat()->setFormatCode('#,##0.00');
		$sheet->getStyle('AD3:AD' . ($row - 1))->getNumberFormat()->setFormatCode('$#,##0.00');

		// 冻结前两行
		$sheet->freezePane('A3');

		// 添加页脚信息
		//$sheet->setCellValue('A' . ($row + 1), '生成时间: ' . date('Y-m-d H:i:s'));
		//$sheet->mergeCells('A' . ($row + 1) . ':AQ' . ($row + 1));
		/*
		$sheet->getStyle('A' . ($row + 1) . ':AQ' . ($row + 1))->applyFromArray([
			'font' => [
				'italic' => true,
				'color' => ['rgb' => '7f8c8d']
			],
			'alignment' => [
				'horizontal' => Alignment::HORIZONTAL_RIGHT
			]
		]);
		*/
		// =============== 输出Excel文件 ===============

		// 设置文件名
		$filename = '产品信息表_' . date('Ymd_His') . '.xlsx';

		// 输出Excel文件
		header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
		header('Content-Disposition: attachment;filename="' . $filename . '"');
		header('Cache-Control: max-age=0');
		header('Expires: 0');
		header('Pragma: public');

		$writer = new Xlsx($spreadsheet);
		$writer->save('php://output');
		exit;
	}
    /****导出供应商****/
    public function exportSupplier(){
        // 模拟数据（实际应用中替换为数据库查询）
        $param = get_params();
        $GoodsModel = new GoodsModel();
        $where = "type = 1 and `desc` !=''";
        if(!empty($param['ids'])){
            $where .=" and id in(".$param['ids'].")";
        }
        if (!empty($param['spu_id'])) {
            $where .= " and spu_id like %".$param['spu_id']."%";
        }
        $admin_id = get_login_admin('id') ? get_login_admin('id') : 0;
        if($admin_id != 1){
            $where  .= ' and admin_id ='.$admin_id;
        }
        $GoodsModel = $GoodsModel::where($where);
        if( !empty($param['start_date']) && !empty($param['end_date']) ) {
            $GoodsModel->whereBetweenTime('create_time',$param['start_date'],date('Y-m-d',strtotime($param['end_date'])+86400));
        }elseif(!empty($param['start_date']) && empty($param['end_date'])){
            $GoodsModel->whereTime('create_time', '>=', strtotime($param['start_date']) );
        }elseif( empty($param['start_date'])  && !empty($param['end_date']) ){
            $GoodsModel->whereTime('create_time', '<=', strtotime($param['end_date'])+86400 );;
        }else{
            $GoodsModel->whereBetweenTime('create_time',date('Y-m-d'),date('Y-m-d',strtotime(date('Y-m-d'))+86400));
        }
        $data  = $GoodsModel
            ->field("ANY_VALUE(banner) AS banner,`desc`")
            ->order('id desc')
            ->select();
        $data = json_decode(json_encode($data),true);


        // 创建新的 Spreadsheet 对象
        $spreadsheet = new Spreadsheet();
        $sheet = $spreadsheet->getActiveSheet();

        // 设置表头
        $headers = [
            '供应商名称', '联系人', '电话', '地址', '网址',
            'QQ', '微信', '旺旺', '结算类型', '备注'
        ];

        // 写入表头（第一行）
        $sheet->fromArray($headers, null, 'A1');

        // 设置表头样式
        $headerStyle = [
            'font' => ['bold' => true, 'color' => ['rgb' => 'FFFFFF']],
            'fill' => ['fillType' => \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID, 'startColor' => ['rgb' => '4F81BD']],
            'alignment' => ['horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER],
            'borders' => ['allBorders' => ['borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN]]
        ];
        $sheet->getStyle('A1:J1')->applyFromArray($headerStyle);

        // 自动调整列宽
        foreach(range('A', 'J') as $col) {
            if($col == 'E'){
                $sheet->getColumnDimension('E')->setWidth(125); // 网址
            }else{
                $sheet->getColumnDimension($col)->setAutoSize(true);
            }

        }

        // 写入数据
        $row = 2; // 从第二行开始
        foreach ($data as $item) {
            $sheet->setCellValue('A' . $row, $item['desc']);
            $sheet->setCellValue('B' . $row, '');

            // 电话列设置为文本格式，防止科学计数法
            $sheet->setCellValueExplicit('C' . $row, '', \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_STRING);

            $sheet->setCellValue('D' . $row, '');

            // 网址设置为超链接
            $sheet->setCellValue('E' . $row, $item['banner']);

            $sheet->setCellValue('F' . $row, '');
            $sheet->setCellValue('G' . $row, '');
            $sheet->setCellValue('H' . $row, '');
            $sheet->setCellValue('I' . $row, '');
            $sheet->setCellValue('J' . $row, '');

            // 设置数据行样式
            $dataStyle = [
                'borders' => ['allBorders' => ['borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN]],
                'alignment' => ['vertical' => \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_TOP]
            ];
            $sheet->getStyle('A' . $row . ':J' . $row)->applyFromArray($dataStyle);

            $row++;
        }

        // 冻结首行（滚动时表头固定）
        $sheet->freezePane('A2');

        // 设置工作表标题
        $sheet->setTitle('供应商信息');

        // 创建 Excel 写入器
        $writer = new Xlsx($spreadsheet);

        // 设置 HTTP 头
        header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
        header('Content-Disposition: attachment;filename="供应商列表_' . date('YmdHis') . '.xlsx"');
        header('Cache-Control: max-age=0');

        // 直接输出到浏览器
        $writer->save('php://output');
        exit;
    }
    /****导出表一****/
    public function exportProducts() {
        $param = get_params();
        $GoodsModel = new GoodsModel();
        $where = [];
        if(!empty($param['spu_id'])){
            $where[]= ['spu_id','in',$param['spu_id']];
        }
        $admin_id = get_login_admin('id') ? get_login_admin('id') : 0;
        if($admin_id != 1){
            $where[] = ['admin_id','=',$admin_id];
        }
        $GoodsModel = $GoodsModel::where($where);
        if( !empty($param['start_date']) && !empty($param['end_date']) ) {
            $GoodsModel->whereBetweenTime('create_time',$param['start_date'],date('Y-m-d',strtotime($param['end_date'])+86400));
        }elseif(!empty($param['start_date']) && empty($param['end_date'])){
            $GoodsModel->whereTime('create_time', '>=', strtotime($param['start_date']) );
        }elseif( empty($param['start_date'])  && !empty($param['end_date']) ){
            $GoodsModel->whereTime('create_time', '<=', strtotime($param['end_date'])+86400 );;
        }else{
            $GoodsModel->whereBetweenTime('create_time',date('Y-m-d'),date('Y-m-d',strtotime(date('Y-m-d'))+86400));
        }
        $data  = $GoodsModel
            ->order('id asc')
            ->select();
        $data = json_decode(json_encode($data),true);
        //$data = $this->removeEmptyShells($data);
        // 设置 PHP 执行时间和内存限制
        ini_set('max_execution_time', 300);
        ini_set('memory_limit', '512M');

        // 定义 CSV 文件名（使用 Shift-JIS 编码）
        $filename = "商品データ_" . date('YmdHis') . ".csv";

        // 设置 HTTP 头 - 明确指定 Shift-JIS 编码

        header('Content-Type: text/csv; charset=Shift_JIS');
        header('Content-Disposition: attachment; filename="' . $filename . '"');
        header('Cache-Control: max-age=0');
        header('Pragma: public');

        // 创建输出流
        $output = fopen('php://output', 'w');

        // 您的表头 JSON
        $headersJson = '["\u5546\u54c1\u7ba1\u7406\u756a\u53f7\uff08\u5546\u54c1URL\uff09","\u5546\u54c1\u756a\u53f7","\u5546\u54c1\u540d","\u5009\u5eab\u6307\u5b9a","\u30b5\u30fc\u30c1\u8868\u793a","\u6d88\u8cbb\u7a0e","\u6d88\u8cbb\u7a0e\u7387","\u8ca9\u58f2\u671f\u9593\u6307\u5b9a\uff08\u958b\u59cb\u65e5\u6642\uff09","\u8ca9\u58f2\u671f\u9593\u6307\u5b9a\uff08\u7d42\u4e86\u65e5\u6642\uff09","\u30dd\u30a4\u30f3\u30c8\u5909\u500d\u7387","\u30dd\u30a4\u30f3\u30c8\u5909\u500d\u7387\u9069\u7528\u671f\u9593\uff08\u958b\u59cb\u65e5\u6642\uff09","\u30dd\u30a4\u30f3\u30c8\u5909\u500d\u7387\u9069\u7528\u671f\u9593\uff08\u7d42\u4e86\u65e5\u6642\uff09","\u6ce8\u6587\u30dc\u30bf\u30f3","\u4e88\u7d04\u5546\u54c1\u767a\u58f2\u65e5","\u5546\u54c1\u554f\u3044\u5408\u308f\u305b\u30dc\u30bf\u30f3","\u95c7\u5e02\u30d1\u30b9\u30ef\u30fc\u30c9","\u5728\u5eab\u8868\u793a","\u4ee3\u5f15\u6599","\u30b8\u30e3\u30f3\u30ebID","\u975e\u88fd\u54c1\u5c5e\u6027\u30bf\u30b0ID","\u30ad\u30e3\u30c3\u30c1\u30b3\u30d4\u30fc","PC\u7528\u5546\u54c1\u8aac\u660e\u6587","\u30b9\u30de\u30fc\u30c8\u30d5\u30a9\u30f3\u7528\u5546\u54c1\u8aac\u660e\u6587","PC\u7528\u8ca9\u58f2\u8aac\u660e\u6587","\u5546\u54c1\u753b\u50cf\u30bf\u30a4\u30d71","\u5546\u54c1\u753b\u50cf\u30d1\u30b91","\u5546\u54c1\u753b\u50cf\u540d\uff08ALT\uff091","\u5546\u54c1\u753b\u50cf\u30bf\u30a4\u30d72","\u5546\u54c1\u753b\u50cf\u30d1\u30b92","\u5546\u54c1\u753b\u50cf\u540d\uff08ALT\uff092","\u5546\u54c1\u753b\u50cf\u30bf\u30a4\u30d73","\u5546\u54c1\u753b\u50cf\u30d1\u30b93","\u5546\u54c1\u753b\u50cf\u540d\uff08ALT\uff093","\u5546\u54c1\u753b\u50cf\u30bf\u30a4\u30d74","\u5546\u54c1\u753b\u50cf\u30d1\u30b94","\u5546\u54c1\u753b\u50cf\u540d\uff08ALT\uff094","\u5546\u54c1\u753b\u50cf\u30bf\u30a4\u30d75","\u5546\u54c1\u753b\u50cf\u30d1\u30b95","\u5546\u54c1\u753b\u50cf\u540d\uff08ALT\uff095","\u5546\u54c1\u753b\u50cf\u30bf\u30a4\u30d76","\u5546\u54c1\u753b\u50cf\u30d1\u30b96","\u5546\u54c1\u753b\u50cf\u540d\uff08ALT\uff096","\u5546\u54c1\u753b\u50cf\u30bf\u30a4\u30d77","\u5546\u54c1\u753b\u50cf\u30d1\u30b97","\u5546\u54c1\u753b\u50cf\u540d\uff08ALT\uff097","\u5546\u54c1\u753b\u50cf\u30bf\u30a4\u30d78","\u5546\u54c1\u753b\u50cf\u30d1\u30b98","\u5546\u54c1\u753b\u50cf\u540d\uff08ALT\uff098","\u5546\u54c1\u753b\u50cf\u30bf\u30a4\u30d79","\u5546\u54c1\u753b\u50cf\u30d1\u30b99","\u5546\u54c1\u753b\u50cf\u540d\uff08ALT\uff099","\u5546\u54c1\u753b\u50cf\u30bf\u30a4\u30d710","\u5546\u54c1\u753b\u50cf\u30d1\u30b910","\u5546\u54c1\u753b\u50cf\u540d\uff08ALT\uff0910","\u5546\u54c1\u753b\u50cf\u30bf\u30a4\u30d711","\u5546\u54c1\u753b\u50cf\u30d1\u30b911","\u5546\u54c1\u753b\u50cf\u540d\uff08ALT\uff0911","\u5546\u54c1\u753b\u50cf\u30bf\u30a4\u30d712","\u5546\u54c1\u753b\u50cf\u30d1\u30b912","\u5546\u54c1\u753b\u50cf\u540d\uff08ALT\uff0912","\u5546\u54c1\u753b\u50cf\u30bf\u30a4\u30d713","\u5546\u54c1\u753b\u50cf\u30d1\u30b913","\u5546\u54c1\u753b\u50cf\u540d\uff08ALT\uff0913","\u5546\u54c1\u753b\u50cf\u30bf\u30a4\u30d714","\u5546\u54c1\u753b\u50cf\u30d1\u30b914","\u5546\u54c1\u753b\u50cf\u540d\uff08ALT\uff0914","\u5546\u54c1\u753b\u50cf\u30bf\u30a4\u30d715","\u5546\u54c1\u753b\u50cf\u30d1\u30b915","\u5546\u54c1\u753b\u50cf\u540d\uff08ALT\uff0915","\u5546\u54c1\u753b\u50cf\u30bf\u30a4\u30d716","\u5546\u54c1\u753b\u50cf\u30d1\u30b916","\u5546\u54c1\u753b\u50cf\u540d\uff08ALT\uff0916","\u5546\u54c1\u753b\u50cf\u30bf\u30a4\u30d717","\u5546\u54c1\u753b\u50cf\u30d1\u30b917","\u5546\u54c1\u753b\u50cf\u540d\uff08ALT\uff0917","\u5546\u54c1\u753b\u50cf\u30bf\u30a4\u30d718","\u5546\u54c1\u753b\u50cf\u30d1\u30b918","\u5546\u54c1\u753b\u50cf\u540d\uff08ALT\uff0918","\u5546\u54c1\u753b\u50cf\u30bf\u30a4\u30d719","\u5546\u54c1\u753b\u50cf\u30d1\u30b919","\u5546\u54c1\u753b\u50cf\u540d\uff08ALT\uff0919","\u5546\u54c1\u753b\u50cf\u30bf\u30a4\u30d720","\u5546\u54c1\u753b\u50cf\u30d1\u30b920","\u5546\u54c1\u753b\u50cf\u540d\uff08ALT\uff0920","\u52d5\u753b","\u767d\u80cc\u666f\u753b\u50cf\u30bf\u30a4\u30d7","\u767d\u80cc\u666f\u753b\u50cf\u30d1\u30b9","\u5546\u54c1\u60c5\u5831\u30ec\u30a4\u30a2\u30a6\u30c8","\u30d8\u30c3\u30c0\u30fc?\u30d5\u30c3\u30bf\u30fc?\u30ec\u30d5\u30c8\u30ca\u30d3","\u8868\u793a\u9805\u76ee\u306e\u4e26\u3073\u9806","\u5171\u901a\u8aac\u660e\u6587\uff08\u5c0f\uff09","\u76ee\u7389\u5546\u54c1","\u5171\u901a\u8aac\u660e\u6587\uff08\u5927\uff09","\u30ec\u30d3\u30e5\u30fc\u672c\u6587\u8868\u793a","\u30e1\u30fc\u30ab\u30fc\u63d0\u4f9b\u60c5\u5831\u8868\u793a","\u30d0\u30ea\u30a8\u30fc\u30b7\u30e7\u30f3\u9805\u76ee\u30ad\u30fc\u5b9a\u7fa9","\u30d0\u30ea\u30a8\u30fc\u30b7\u30e7\u30f3\u9805\u76ee\u540d\u5b9a\u7fa9","\u30d0\u30ea\u30a8\u30fc\u30b7\u30e7\u30f31\u9078\u629e\u80a2\u5b9a\u7fa9","\u30d0\u30ea\u30a8\u30fc\u30b7\u30e7\u30f32\u9078\u629e\u80a2\u5b9a\u7fa9","\u30d0\u30ea\u30a8\u30fc\u30b7\u30e7\u30f33\u9078\u629e\u80a2\u5b9a\u7fa9","\u30d0\u30ea\u30a8\u30fc\u30b7\u30e7\u30f34\u9078\u629e\u80a2\u5b9a\u7fa9","\u30d0\u30ea\u30a8\u30fc\u30b7\u30e7\u30f35\u9078\u629e\u80a2\u5b9a\u7fa9","\u30d0\u30ea\u30a8\u30fc\u30b7\u30e7\u30f36\u9078\u629e\u80a2\u5b9a\u7fa9","\u9078\u629e\u80a2\u30bf\u30a4\u30d7","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9805\u76ee\u540d","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a21","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a22","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a23","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a24","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a25","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a26","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a27","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a28","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a29","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a210","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a211","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a212","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a213","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a214","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a215","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a216","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a217","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a218","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a219","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a220","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a221","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a222","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a223","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a224","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a225","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a226","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a227","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a228","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a229","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a230","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a231","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a232","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a233","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a234","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a235","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a236","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a237","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a238","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a239","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a240","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a241","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a242","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a243","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a244","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a245","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a246","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a247","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a248","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a249","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a250","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a251","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a252","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a253","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a254","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a255","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a256","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a257","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a258","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a259","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a260","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a261","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a262","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a263","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a264","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a265","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a266","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a267","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a268","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a269","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a270","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a271","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a272","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a273","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a274","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a275","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a276","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a277","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a278","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a279","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a280","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a281","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a282","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a283","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a284","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a285","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a286","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a287","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a288","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a289","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a290","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a291","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a292","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a293","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a294","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a295","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a296","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a297","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a298","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a299","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u80a2100","\u5546\u54c1\u30aa\u30d7\u30b7\u30e7\u30f3\u9078\u629e\u5fc5\u9808","SKU\u7ba1\u7406\u756a\u53f7","\u30b7\u30b9\u30c6\u30e0\u9023\u643a\u7528SKU\u756a\u53f7","\u30d0\u30ea\u30a8\u30fc\u30b7\u30e7\u30f3\u9805\u76ee\u30ad\u30fc1","\u30d0\u30ea\u30a8\u30fc\u30b7\u30e7\u30f3\u9805\u76ee\u9078\u629e\u80a21","\u30d0\u30ea\u30a8\u30fc\u30b7\u30e7\u30f3\u9805\u76ee\u30ad\u30fc2","\u30d0\u30ea\u30a8\u30fc\u30b7\u30e7\u30f3\u9805\u76ee\u9078\u629e\u80a22","\u30d0\u30ea\u30a8\u30fc\u30b7\u30e7\u30f3\u9805\u76ee\u30ad\u30fc3","\u30d0\u30ea\u30a8\u30fc\u30b7\u30e7\u30f3\u9805\u76ee\u9078\u629e\u80a23","\u30d0\u30ea\u30a8\u30fc\u30b7\u30e7\u30f3\u9805\u76ee\u30ad\u30fc4","\u30d0\u30ea\u30a8\u30fc\u30b7\u30e7\u30f3\u9805\u76ee\u9078\u629e\u80a24","\u30d0\u30ea\u30a8\u30fc\u30b7\u30e7\u30f3\u9805\u76ee\u30ad\u30fc5","\u30d0\u30ea\u30a8\u30fc\u30b7\u30e7\u30f3\u9805\u76ee\u9078\u629e\u80a25","\u30d0\u30ea\u30a8\u30fc\u30b7\u30e7\u30f3\u9805\u76ee\u30ad\u30fc6","\u30d0\u30ea\u30a8\u30fc\u30b7\u30e7\u30f3\u9805\u76ee\u9078\u629e\u80a26","\u8ca9\u58f2\u4fa1\u683c","\u8868\u793a\u4fa1\u683c","\u4e8c\u91cd\u4fa1\u683c\u6587\u8a00\u7ba1\u7406\u756a\u53f7","\u6ce8\u6587\u53d7\u4ed8\u6570","\u518d\u5165\u8377\u304a\u77e5\u3089\u305b\u30dc\u30bf\u30f3","\u306e\u3057\u5bfe\u5fdc","\u5728\u5eab\u6570","\u5728\u5eab\u623b\u3057\u30d5\u30e9\u30b0","\u5728\u5eab\u5207\u308c\u6642\u306e\u6ce8\u6587\u53d7\u4ed8","\u5728\u5eab\u3042\u308a\u6642\u7d0d\u671f\u7ba1\u7406\u756a\u53f7","\u5728\u5eab\u5207\u308c\u6642\u7d0d\u671f\u7ba1\u7406\u756a\u53f7","\u5728\u5eab\u3042\u308a\u6642\u51fa\u8377\u30ea\u30fc\u30c9\u30bf\u30a4\u30e0","\u5728\u5eab\u5207\u308c\u6642\u51fa\u8377\u30ea\u30fc\u30c9\u30bf\u30a4\u30e0","SKU\u5009\u5eab\u6307\u5b9a","\u914d\u9001\u65b9\u6cd5\u30bb\u30c3\u30c8\u7ba1\u7406\u756a\u53f7","\u9001\u6599","\u9001\u6599\u533a\u52061","\u9001\u6599\u533a\u52062","\u500b\u5225\u9001\u6599","\u5730\u57df\u5225\u500b\u5225\u9001\u6599\u7ba1\u7406\u756a\u53f7","\u5358\u54c1\u914d\u9001\u8a2d\u5b9a\u4f7f\u7528","\u30ab\u30bf\u30ed\u30b0ID","\u30ab\u30bf\u30ed\u30b0ID\u306a\u3057\u306e\u7406\u7531","\u30bb\u30c3\u30c8\u5546\u54c1\u7528\u30ab\u30bf\u30ed\u30b0ID","SKU\u753b\u50cf\u30bf\u30a4\u30d7","SKU\u753b\u50cf\u30d1\u30b9","SKU\u753b\u50cf\u540d\uff08ALT\uff09","\u5546\u54c1\u5c5e\u6027\uff08\u9805\u76ee\uff091","\u5546\u54c1\u5c5e\u6027\uff08\u5024\uff091","\u5546\u54c1\u5c5e\u6027\uff08\u5358\u4f4d\uff091","\u5546\u54c1\u5c5e\u6027\uff08\u9805\u76ee\uff092","\u5546\u54c1\u5c5e\u6027\uff08\u5024\uff092","\u5546\u54c1\u5c5e\u6027\uff08\u5358\u4f4d\uff092","\u5546\u54c1\u5c5e\u6027\uff08\u9805\u76ee\uff093","\u5546\u54c1\u5c5e\u6027\uff08\u5024\uff093","\u5546\u54c1\u5c5e\u6027\uff08\u5358\u4f4d\uff093","\u5546\u54c1\u5c5e\u6027\uff08\u9805\u76ee\uff094","\u5546\u54c1\u5c5e\u6027\uff08\u5024\uff094","\u5546\u54c1\u5c5e\u6027\uff08\u5358\u4f4d\uff094","\u5546\u54c1\u5c5e\u6027\uff08\u9805\u76ee\uff095","\u5546\u54c1\u5c5e\u6027\uff08\u5024\uff095","\u5546\u54c1\u5c5e\u6027\uff08\u5358\u4f4d\uff095","\u5546\u54c1\u5c5e\u6027\uff08\u9805\u76ee\uff096","\u5546\u54c1\u5c5e\u6027\uff08\u5024\uff096","\u5546\u54c1\u5c5e\u6027\uff08\u5358\u4f4d\uff096","\u5546\u54c1\u5c5e\u6027\uff08\u9805\u76ee\uff097","\u5546\u54c1\u5c5e\u6027\uff08\u5024\uff097","\u5546\u54c1\u5c5e\u6027\uff08\u5358\u4f4d\uff097","\u5546\u54c1\u5c5e\u6027\uff08\u9805\u76ee\uff098","\u5546\u54c1\u5c5e\u6027\uff08\u5024\uff098","\u5546\u54c1\u5c5e\u6027\uff08\u5358\u4f4d\uff098","\u5546\u54c1\u5c5e\u6027\uff08\u9805\u76ee\uff099","\u5546\u54c1\u5c5e\u6027\uff08\u5024\uff099","\u5546\u54c1\u5c5e\u6027\uff08\u5358\u4f4d\uff099","\u5546\u54c1\u5c5e\u6027\uff08\u9805\u76ee\uff0910","\u5546\u54c1\u5c5e\u6027\uff08\u5024\uff0910","\u5546\u54c1\u5c5e\u6027\uff08\u5358\u4f4d\uff0910","\u5546\u54c1\u5c5e\u6027\uff08\u9805\u76ee\uff0911","\u5546\u54c1\u5c5e\u6027\uff08\u5024\uff0911","\u5546\u54c1\u5c5e\u6027\uff08\u5358\u4f4d\uff0911","\u5546\u54c1\u5c5e\u6027\uff08\u9805\u76ee\uff0912","\u5546\u54c1\u5c5e\u6027\uff08\u5024\uff0912","\u5546\u54c1\u5c5e\u6027\uff08\u5358\u4f4d\uff0912","\u5546\u54c1\u5c5e\u6027\uff08\u9805\u76ee\uff0913","\u5546\u54c1\u5c5e\u6027\uff08\u5024\uff0913","\u5546\u54c1\u5c5e\u6027\uff08\u5358\u4f4d\uff0913","\u5546\u54c1\u5c5e\u6027\uff08\u9805\u76ee\uff0914","\u5546\u54c1\u5c5e\u6027\uff08\u5024\uff0914","\u5546\u54c1\u5c5e\u6027\uff08\u5358\u4f4d\uff0914","\u5546\u54c1\u5c5e\u6027\uff08\u9805\u76ee\uff0915","\u5546\u54c1\u5c5e\u6027\uff08\u5024\uff0915","\u5546\u54c1\u5c5e\u6027\uff08\u5358\u4f4d\uff0915","\u5546\u54c1\u5c5e\u6027\uff08\u9805\u76ee\uff0916","\u5546\u54c1\u5c5e\u6027\uff08\u5024\uff0916","\u5546\u54c1\u5c5e\u6027\uff08\u5358\u4f4d\uff0916","\u5546\u54c1\u5c5e\u6027\uff08\u9805\u76ee\uff0917","\u5546\u54c1\u5c5e\u6027\uff08\u5024\uff0917","\u5546\u54c1\u5c5e\u6027\uff08\u5358\u4f4d\uff0917","\u5546\u54c1\u5c5e\u6027\uff08\u9805\u76ee\uff0918","\u5546\u54c1\u5c5e\u6027\uff08\u5024\uff0918","\u5546\u54c1\u5c5e\u6027\uff08\u5358\u4f4d\uff0918","\u5546\u54c1\u5c5e\u6027\uff08\u9805\u76ee\uff0919","\u5546\u54c1\u5c5e\u6027\uff08\u5024\uff0919","\u5546\u54c1\u5c5e\u6027\uff08\u5358\u4f4d\uff0919","\u5546\u54c1\u5c5e\u6027\uff08\u9805\u76ee\uff0920","\u5546\u54c1\u5c5e\u6027\uff08\u5024\uff0920","\u5546\u54c1\u5c5e\u6027\uff08\u5358\u4f4d\uff0920","\u5546\u54c1\u5c5e\u6027\uff08\u9805\u76ee\uff0921","\u5546\u54c1\u5c5e\u6027\uff08\u5024\uff0921","\u5546\u54c1\u5c5e\u6027\uff08\u5358\u4f4d\uff0921","\u5546\u54c1\u5c5e\u6027\uff08\u9805\u76ee\uff0922","\u5546\u54c1\u5c5e\u6027\uff08\u5024\uff0922","\u5546\u54c1\u5c5e\u6027\uff08\u5358\u4f4d\uff0922","\u5546\u54c1\u5c5e\u6027\uff08\u9805\u76ee\uff0923","\u5546\u54c1\u5c5e\u6027\uff08\u5024\uff0923","\u5546\u54c1\u5c5e\u6027\uff08\u5358\u4f4d\uff0923","\u5546\u54c1\u5c5e\u6027\uff08\u9805\u76ee\uff0924","\u5546\u54c1\u5c5e\u6027\uff08\u5024\uff0924","\u5546\u54c1\u5c5e\u6027\uff08\u5358\u4f4d\uff0924","\u5546\u54c1\u5c5e\u6027\uff08\u9805\u76ee\uff0925","\u5546\u54c1\u5c5e\u6027\uff08\u5024\uff0925","\u5546\u54c1\u5c5e\u6027\uff08\u5358\u4f4d\uff0925","\u5546\u54c1\u5c5e\u6027\uff08\u9805\u76ee\uff0926","\u5546\u54c1\u5c5e\u6027\uff08\u5024\uff0926","\u5546\u54c1\u5c5e\u6027\uff08\u5358\u4f4d\uff0926","\u5546\u54c1\u5c5e\u6027\uff08\u9805\u76ee\uff0927","\u5546\u54c1\u5c5e\u6027\uff08\u5024\uff0927","\u5546\u54c1\u5c5e\u6027\uff08\u5358\u4f4d\uff0927","\u5546\u54c1\u5c5e\u6027\uff08\u9805\u76ee\uff0928","\u5546\u54c1\u5c5e\u6027\uff08\u5024\uff0928","\u5546\u54c1\u5c5e\u6027\uff08\u5358\u4f4d\uff0928","\u5546\u54c1\u5c5e\u6027\uff08\u9805\u76ee\uff0929","\u5546\u54c1\u5c5e\u6027\uff08\u5024\uff0929","\u5546\u54c1\u5c5e\u6027\uff08\u5358\u4f4d\uff0929","\u5546\u54c1\u5c5e\u6027\uff08\u9805\u76ee\uff0930","\u5546\u54c1\u5c5e\u6027\uff08\u5024\uff0930","\u5546\u54c1\u5c5e\u6027\uff08\u5358\u4f4d\uff0930","\u5546\u54c1\u5c5e\u6027\uff08\u9805\u76ee\uff0931","\u5546\u54c1\u5c5e\u6027\uff08\u5024\uff0931","\u5546\u54c1\u5c5e\u6027\uff08\u5358\u4f4d\uff0931","\u5546\u54c1\u5c5e\u6027\uff08\u9805\u76ee\uff0932","\u5546\u54c1\u5c5e\u6027\uff08\u5024\uff0932","\u5546\u54c1\u5c5e\u6027\uff08\u5358\u4f4d\uff0932","\u81ea\u7531\u5165\u529b\u884c\uff08\u9805\u76ee\uff091","\u81ea\u7531\u5165\u529b\u884c\uff08\u5024\uff091","\u81ea\u7531\u5165\u529b\u884c\uff08\u9805\u76ee\uff092","\u81ea\u7531\u5165\u529b\u884c\uff08\u5024\uff092","\u81ea\u7531\u5165\u529b\u884c\uff08\u9805\u76ee\uff093","\u81ea\u7531\u5165\u529b\u884c\uff08\u5024\uff093","\u81ea\u7531\u5165\u529b\u884c\uff08\u9805\u76ee\uff094","\u81ea\u7531\u5165\u529b\u884c\uff08\u5024\uff094","\u81ea\u7531\u5165\u529b\u884c\uff08\u9805\u76ee\uff095","\u81ea\u7531\u5165\u529b\u884c\uff08\u5024\uff095"]';

        // 解析表头
        $headers = json_decode($headersJson, true);
        if ($headers === null) {
            die('无效的表头JSON格式');
        }
        // 转换表头为 Shift-JIS 编码
        $sjisHeaders = [];
        foreach ($headers as $header) {
            $sjisHeaders[] = $this->convertToShiftJis($header);
        }

        // 写入表头（使用 Windows CR LF 行尾符）
        fwrite($output, implode(',', array_map([$this, 'encodeCsvField'], $sjisHeaders)) . "\r\n");

        // 分批处理数据
        $total = count($data);

        for ($i = 0; $i < $total; $i ++) {
            $intro = !empty($data[$i]['intro']) ? json_decode($data[$i]['intro'],true) : [];
            $csvRow = [];
            foreach ($headers as $key => $header) {
                $value = $intro[$key] ?? '';
                if($key == 2){
                    $value = $data[$i]['title'];
                }elseif($key == 96){
                    $parts = [$data[$i]['sku_key']];
                    if (!empty($data[$i]['sku_key2'])) {
                        $parts[] = $data[$i]['sku_key2'];
                    }
                    if (!empty($data[$i]['sku_key3'])) {
                        $parts[] = $data[$i]['sku_key3'];
                    }
                    $value = implode('|', $parts);
                }elseif($key == 97){
                    $value = $data[$i]['sku_value'];
                }elseif($key == 98){
                    $value = $data[$i]['sku_value2'];
                }elseif($key == 99){
                    $value = $data[$i]['sku_value3'];
                }elseif( $key == 226){
                    if($data[$i]['type'] == 1){
                        $value = "";
                    }else{
                        $value = $data[$i]['stocks'] == 0 ? 5 : $data[$i]['stocks'] ;
                    }
                }elseif( $key == 220){
                    $value = $data[$i]['type'] == 1 ? '' : $data[$i]['base_price'];
                }
                $csvRow[] = $this->convertToShiftJis($this->formatCellValue($value));
            }

            // 写入一行数据（使用 Windows CR LF 行尾符）
            fwrite($output, implode(',', array_map([$this, 'encodeCsvField'], $csvRow)) . "\r\n");
            // 刷新输出缓冲区
            flush();

            // 定期释放内存
            if ($i % 1000 === 0) {
                gc_collect_cycles();
            }
        }
        // 关闭输出流
        fclose($output);
        exit;
    }
    /**
     * 将全角数字转换为半角数字
     * 主要用于处理价格、数量等数字字段
     *
     * @param mixed $value 输入值（可以是字符串、数字或其他类型）
     * @return mixed 转换后的值
     */
    protected function convertToHalfWidthNumeric($value)
    {
        // 如果是空值，直接返回
        if ($value === null || $value === '') {
            return $value;
        }

        // 如果是数字类型，直接返回（已经是半角）
        if (is_numeric($value)) {
            return $value;
        }

        // 转换为字符串处理
        $stringValue = (string)$value;

        // 全角数字到半角数字的映射
        $fullWidthToHalfWidth = [
            '０' => '0', '１' => '1', '２' => '2', '３' => '3', '４' => '4',
            '５' => '5', '６' => '6', '７' => '7', '８' => '8', '９' => '9',
            '．' => '.', // 全角小数点转半角
            '，' => ',', // 全角逗号转半角（用于千位分隔符）
        ];

        // 执行转换
        $convertedValue = strtr($stringValue, $fullWidthToHalfWidth);

        // 移除可能存在的货币符号和空格
        $convertedValue = preg_replace('/[^\d.,-]/', '', $convertedValue);

        // 如果是价格字段，可以尝试转换为浮点数
        if (preg_match('/^-?\d+([.,]\d+)?$/', $convertedValue)) {
            // 将逗号替换为点（如果是千位分隔符，需要先移除）
            if (strpos($convertedValue, ',') !== false && strpos($convertedValue, '.') !== false) {
                // 同时存在逗号和点，假设逗号是千位分隔符
                $convertedValue = str_replace(',', '', $convertedValue);
            } else {
                // 只有逗号，可能是欧洲数字格式（用逗号表示小数点）
                $convertedValue = str_replace(',', '.', $convertedValue);
            }

            // 转换为浮点数
            return (float)$convertedValue;
        }

        return $convertedValue;
    }
    /**
     * CSV 字段编码（处理逗号、引号等特殊字符）
     */
    protected function encodeCsvField($field)
    {
        // 如果字段包含逗号、双引号或换行符，需要用双引号括起来
        if (strpos($field, ',') !== false || strpos($field, '"') !== false || strpos($field, "\n") !== false || strpos($field, "\r") !== false) {
            // 转义双引号
            $field = str_replace('"', '""', $field);
            return '"' . $field . '"';
        }

        return $field;
    }
    /**
     * 将字符串转换为 Shift-JIS 编码
     */
    protected function convertToShiftJis($string)
    {
        if ($string === null || $string === '') {
            return '';
        }

        // 确保是字符串
        if (!is_string($string)) {
            $string = (string)$string;
        }

        // 检测当前编码
        $encoding = mb_detect_encoding($string, ['UTF-8', 'SJIS', 'EUC-JP', 'ASCII'], true);

        // 如果已经是 Shift-JIS，直接返回
        if ($encoding === 'SJIS') {
            return $string;
        }

        // 转换为 Shift-JIS
        if (function_exists('mb_convert_encoding')) {
            $result = mb_convert_encoding($string, 'SJIS', 'UTF-8');
            // 验证转换结果
            if (mb_detect_encoding($result, ['SJIS'], true) === 'SJIS') {
                return $result;
            }
        }

        if (function_exists('iconv')) {
            $result = iconv('UTF-8', 'SJIS//TRANSLIT', $string);
            if ($result !== false) {
                return $result;
            }
        }

        // 如果转换失败，尝试使用自定义映射
        return $this->utf8ToSjisManual($string);
    }
    /**
     * 手动 UTF-8 到 Shift-JIS 转换（简化版）
     */
    protected function utf8ToSjisManual($string)
    {
        // 简化的映射表
        $mapping = [
            'あ' => "\x82\xA0", 'い' => "\x82\xA2", 'う' => "\x82\xA4",
            'え' => "\x82\xA6", 'お' => "\x82\xA8",
            'ア' => "\x83\x41", 'イ' => "\x83\x43", 'ウ' => "\x83\x45",
            'エ' => "\x83\x47", 'オ' => "\x83\x49",
            '。' => "\x81\x43", '、' => "\x81\x42", 'ー' => "\x81\x5B",
            // 更多字符映射...
        ];

        // 替换映射表中的字符
        return strtr($string, $mapping);
    }
    //去重
    public function removeEmptyShells(array &$data)
    {
        // 第一步：收集所有需要删除的壳的ID
        $shellIdsToRemove = [];
        foreach ($data as $key => $item) {
            if ($item['type'] == 1 && empty($item['sku_value'])) {
                $shellIdsToRemove[] = $item['spu_id']; // 记录需要删除的壳的索引
            }
        }
        // 第二步：删除壳及其所有子集
        foreach ($data as $key => $item) {
            // 如果是需要删除的壳本身
            if (in_array($item['spu_id'], $shellIdsToRemove)) {
                unset($data[$key]);
                continue;
            }
        }
        return array_values($data);
    }
    // 单元格值格式化
    private function formatCellValue($value) {
        // 空值处理
        if ($value === null || $value === '') {
            return '';
        }
        // 处理日期格式
        if ($value instanceof DateTime) {
            return $value->format('Y-m-d H:i:s');
        }

        // 处理长数字（防止科学计数法）
        if (is_numeric($value) && strlen((string)$value) > 10) {
            return ' ' . $value; // 前面加空格强制文本格式
        }

        // 处理超长文本
        if (is_string($value) && strlen($value) > 32700) {
            return substr($value, 0, 32700) . '... [截断]';
        }

        return $value;
    }

    //图片拼接
	private function buildImagePathString(array $images, string $domainPath = 'https://example.com/images/'): string {
        // 处理域名路径
        $cleanPath = rtrim(trim($domainPath), '/') . '/';

        // 使用Excel强制换行符
        $result = '';
        foreach ($images as $image) {
            if(!empty($image)){
                $cleanImage = ltrim(trim($image), '/');
                $fullPath = $cleanPath . $cleanImage;

                // 每条路径后添加Excel换行符
                $result .= $fullPath . "\r\n"; // 使用CRLF换行符
            }
        }

        // 返回结果（保留最后一个换行符）
        return $result;
    }
    private function splitString($string) {
        $pattern = '/[\s,;:\/|　，；：、。]+/u';
        // 分割字符串并移除空元素
        $result = preg_split($pattern, $string, -1, PREG_SPLIT_NO_EMPTY);
        return $result ?: []; // 确保始终返回数组
    }

    private function arrayCombineWithKeys(array $arr1, array $arr2 = [], ?array $arr3 = null): array {
        $result = [];

        // 收集所有非空数组
        $arrays = [];
        if (!empty($arr1)) {
            $arrays[] = $arr1;
        }
        if (!empty($arr2)) {
            $arrays[] = $arr2;
        }
        if ($arr3 !== null && !empty($arr3)) {
            $arrays[] = $arr3;
        }

        // 处理所有数组都为空的情况
        if (empty($arrays)) {
            return [];
        }

        // 计算笛卡尔积
        $combinations = [[]];
        foreach ($arrays as $array) {
            $temp = [];
            foreach ($combinations as $combination) {
                foreach ($array as $value) {
                    $temp[] = array_merge($combination, [$value]);
                }
            }
            $combinations = $temp;
        }

        // 生成结果数组，键为组合值的拼接
        foreach ($combinations as $combination) {
            $key = implode('_', array_map(function($v) {
                return is_scalar($v) ? (string)$v : json_encode($v);
            }, $combination));
            $result[$key] = $combination;
        }

        return $result;
    }
    //获取权限树所需的节点列表
    public function get_rule()
    {
        $rule = get_admin_rule();
        $group = [];
        if (!empty(get_params('id'))) {
            $group = get_admin_group_info(get_params('id'))['rules'];
        }
        $list = create_tree_list(0, $rule, $group);
        return to_assign(0, '', $list);
    }

    //获取关键字
    public function get_keyword_cate()
    {
        $keyword = get_keywords();
        return to_assign(0, '', $keyword);
    }

    //获取话题
    public function get_topics_cate()
    {
        $topic = get_topics();
        return to_assign(0, '', $topic);
    }

    //清空缓存
    public function cache_clear()
    {
        \think\facade\Cache::clear();
        return to_assign(0, '系统缓存已清空');
    }

    //发送测试邮件
    public function email_to($email)
    {
        $name = empty(get_config('webconfig.admin_title')) ? '系统' : get_config('webconfig.admin_title');
        if (send_email($email, "一封来自{$name}的测试邮件。")) {
            return to_assign(0, '发送成功，请注意查收');
        }
        return to_assign(1, '发送失败');
    }

    //修改个人信息
    public function edit_personal()
    {
        return view('admin/edit_personal', [
            'admin' => get_login_admin(),
        ]);
    }

    //保存个人信息修改
    public function personal_submit()
    {
        if (request()->isAjax()) {
            $param = get_params();
            try {
                validate(AdminCheck::class)->scene('editPersonal')->check($param);
            } catch (ValidateException $e) {
                // 验证失败 输出错误信息
                return to_assign(1, $e->getError());
            }
            unset($param['username']);
            $uid = get_login_admin('id');
            Db::name('Admin')->where([
                'id' => $uid,
            ])->strict(false)->field(true)->update($param);
            $session_admin = get_config('app.session_admin');
            Session::set($session_admin, Db::name('admin')->find($uid));
            return to_assign();
        }
    }

    //修改密码
    public function edit_password()
    {
        return view('admin/edit_password', [
            'admin' => get_login_admin(),
        ]);
    }

    //保存密码修改
    public function password_submit()
    {
        if (request()->isAjax()) {
            $param = get_params();
            try {
                validate(AdminCheck::class)->scene('editpwd')->check($param);
            } catch (ValidateException $e) {
                // 验证失败 输出错误信息
                return to_assign(1, $e->getError());
            }
            $admin = get_login_admin();
            if (set_password($param['old_pwd'], $admin['salt']) !== $admin['pwd']) {
                return to_assign(1, '旧密码不正确!');
            }
            unset($param['username']);
            $param['salt'] = set_salt(20);
            $param['pwd'] = set_password($param['pwd'], $param['salt']);
            Db::name('Admin')->where([
                'id' => $admin['id'],
            ])->strict(false)->field(true)->update($param);
            $session_admin = get_config('app.session_admin');
            Session::set($session_admin, Db::name('admin')->find($admin['id']));
            return to_assign();
        }
    }

    // 测试邮件发送
    public function email_test()
    {
        $sender = get_params('email');
        //检查是否邮箱格式		
		$validate = \think\facade\Validate::rule([
			'email' => 'email'
		]);

		$data = [
			'email' => $sender
		];

		if (!$validate->check($data)) {
			return to_assign(1, $validate->getError());
		}		
		
        $email_config = \think\facade\Db::name('config')->where('name', 'email')->find();
        $config = unserialize($email_config['content']);
        $content = $config['template'];
        //所有项目必须填写
        if (empty($config['smtp']) || empty($config['smtp_port']) || empty($config['smtp_user']) || empty($config['smtp_pwd'])) {
            return to_assign(1, '请完善邮件配置信息！');
        }

        $send = send_email($sender, '测试邮件', $content);
        if ($send) {
            return to_assign(0, '邮件发送成功！');
        } else {
            return to_assign(1, '邮件发送失败！');
        }
    }

    //首页获取
    public function get_admin_list()
    {
        $content = Db::name('Admin')
            ->where(['status' => 1])
            ->order('id desc')
            ->limit(10)
            ->select()->toArray();
        $res['data'] = $content;
        return table_assign(0, '', $res);
    }

    //首页获取最新10位用户
    public function get_user_list()
    {
        $list = Db::name('User')
            ->where(['status' => 1])
            ->order('id desc')
            ->limit(10)
            ->select()->toArray();
        foreach ($list as $key => $val) {
            $list[$key]['last_login_time'] = date('Y-m-d H:i:s', $val['last_login_time']);
        }
        $res['data'] = $list;
        return table_assign(0, '', $res);
    }

    //首页文章
    public function get_article_list()
    {
        $list = Db::name('Article')
            ->field('a.id,a.title,a.read,a.status,a.create_time,c.title as cate_title')
            ->alias('a')
            ->join('article_cate c', 'a.cate_id = c.id')
            ->where(['a.delete_time' => 0])
            ->order('a.id desc')
            ->limit(10)
            ->select()->toArray();
        foreach ($list as $key => $val) {
            $list[$key]['create_time'] = date('Y-m-d H:i', $val['create_time']);
        }
        $res['data'] = $list;
        return table_assign(0, '', $res);
    }
	
    //首页商品
    public function get_goods_list()
    {
        $list = Db::name('Goods')
            ->field('a.*,c.title as cate_title,u.nickname as admin_name')
			->alias('a')
			->join('GoodsCate c', 'a.cate_id = c.id')
			->join('Admin u', 'a.admin_id = u.id')
            ->where(['a.delete_time' => 0,'a.status'=>1])
            ->order('a.id desc')
            ->limit(10)
            ->select()->toArray();
        foreach ($list as $key => $val) {
            $list[$key]['create_time'] = date('Y-m-d H:i', $val['create_time']);
        }
        $res['data'] = $list;
        return table_assign(0, '', $res);
    }

    //首页图集
    public function get_gallery_list()
    {
        $list = Db::name('Gallery')
            ->field('a.*,c.title as cate_title,u.nickname as admin_name')
			->alias('a')
			->join('GalleryCate c', 'a.cate_id = c.id')
			->join('Admin u', 'a.admin_id = u.id')
            ->where(['a.delete_time' => 0,'a.status'=>1])
            ->order('a.id desc')
            ->limit(10)
            ->select()->toArray();
        foreach ($list as $key => $val) {
            $list[$key]['create_time'] = date('Y-m-d H:i', $val['create_time']);
			$list[$key]['count']  = Db::name('GalleryFile')->where(array('aid'=>$val['id']))->count();
        }
        $res['data'] = $list;
        return table_assign(0, '', $res);
    }

    //系统操作日志
    public function log_list()
    {
        return view('admin/log_list');
    }

    //获取系统操作日志
    public function get_log_list()
    {
        $param = get_params();
        $log = new AdminLog();
        $content = $log->get_log_list($param);
        return table_assign(0, '', $content);
    }
    //获取系统操作日志
    public function get_sku_data()
    {
        $param = get_params();
        $good_data =Db::name('goods')->where("spu_id = '".$param['spu_id']."' and type = 1")
            ->field('id,caigou,base_price,wuliu,stocks,commission')
            ->find();
        $nav =Db::name('Nav')->field('id,title,desc')->where(['id'=>$param['commission']])
            ->find();
        $sku_data =Db::name('goods')->where("spu_id = '".$param['spu_id']."' and type = 2")
            ->field('id,sku_id,base_price,stocks,intro')
            ->select();
        $data = array();
        foreach ($sku_data as $key=>$value){
            //$commission = isset($value['commission']) ? json_decode($value['commission'],true) : '';
            /*
            if(!empty($nav)){
                $desc = json_decode($nav['desc'],true);
                $calculate =  $this->calculateProfitMetrics(
                    (float)$value['base_price'],
                    (float)$good_data['caigou'],
                    (float)$good_data['wuliu'],
                    (float)$desc[0]*0.01,
                    (float)$desc[1]*0.01,
                    (float)$desc[2]*0.01,
                    );
            }*/
            $intro = isset($value['intro']) ? json_decode($value['intro'],true) : '';

            $data[] = [
                'id'=> $value['id'],
                'sku_id'=> $value['sku_id'],
                'base_price'=> $value['base_price'],
                'stocks'=> $value['stocks'],
                '209'=> $intro[209],
                '211'=> $intro[211],
                //'platform_commission'  => !empty($calculate['platform_commission']) ? $calculate['platform_commission'] : 0,
                //'ad'                   => !empty($calculate['ad_cost']) ? $calculate['ad_cost'] : 0,
                //'shop_owner_commission'=> !empty($calculate['owner_commission']) ? $calculate['owner_commission'] : 0,
                //'payment'              => !empty($calculate['refund']) ? $calculate['refund'] : 0,
                //'profit'               => !empty($calculate['profit']) ? $calculate['profit'] : 0,
                //'profit_rate'          => !empty($calculate['profit_rate']) ? $calculate['profit_rate'] : 0,
            ];
        }
        return to_assign(0, '',$data);
    }
    private function calculateProfitMetrics(
        float $salePrice,       // 售价
        float $purchasePrice,   // 采购价
        float $logistics,       // 物流费用
        float $platformRate,    // 平台佣金比例 (小数形式)
        float $adRate,          // 广告比例 (小数形式)
        float $ownerRate        // 店主抽佣比例 (小数形式)
    ): array {
        // 计算各项费用 (保留两位小数)
        $platformCommission = round($salePrice * $platformRate, 2);
        $adCost = round($salePrice * $adRate, 2);

        // 店主抽佣基数 = 售价 - 平台佣金 - 广告
        $ownerBase = $salePrice - $platformCommission - $adCost;
        $ownerCommission = round($ownerBase * $ownerRate, 2);

        // 计算回款和利润
        $refund = round($salePrice - $platformCommission - $adCost - $ownerCommission, 2);
        $profit = round($refund - $purchasePrice - $logistics, 2);

        // 计算利润率 (处理除零错误)
        $profitRate = ($salePrice > 0) ? $profit / $salePrice : 0;

        return [
            'platform_commission' => $platformCommission,
            'ad_cost' => $adCost,
            'owner_commission' => $ownerCommission,
            'refund' => $refund,
            'profit' => $profit,
            'profit_rate' => round($profitRate,2)
        ];
    }

    //获取访问记录
    public function get_view_data()
    {
        $param = get_params();
        $first_time = time();
        $second_time = $first_time - 86400;
        $three_time = $first_time - 86400*365;
        $begin_first = strtotime(date('Y-m-d', $first_time) . " 00:00:00");
        $end_first = strtotime(date('Y-m-d', $first_time) . " 23:59:59");
        $begin_second = strtotime(date('Y-m-d', $second_time) . " 00:00:00");
        $end_second = strtotime(date('Y-m-d', $second_time) . " 23:59:59");
		$begin_three = strtotime(date('Y-m-d', $three_time) . " 00:00:00");
        $data_first = Db::name('UserLog')->field('create_time')->whereBetween('create_time', "$begin_first,$end_first")->select();
        $data_second = Db::name('UserLog')->field('create_time')->whereBetween('create_time', "$begin_second,$end_second")->select();

		$data_three = Db::name('UserLog')->field('create_time')->whereBetween('create_time', "$begin_three,$end_first")->select();		
		
        return to_assign(0, '', ['data_first' => hour_document($data_first), 'data_second' => hour_document($data_second), 'data_three'=>date_document($data_three)]);
    }

}
